package com.sinooceangroup.capital.sentinel.service.impl;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.sinooceangroup.capital.sentinel.service.SentinelService;
import org.springframework.stereotype.Service;

import java.util.Random;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * Sentinel Service Demo
 *
 * @author: Leo.Wang, adwyxx@qq.com
 * @date: 2020/8/5 10:13
 */
@Service
public class SentinelServiceImpl implements SentinelService {
    /***
     * 使用  @SentinelResource 注解用来标识资源是否被限流、降级
     */
    @Override
    @SentinelResource(value = "sayHello")
    public String sayHello(String name) {
        return "Hello "+name+"! o(∩_∩)o 哈哈";
    }

    /***
     * 可以使用 blockHandler 属性指定限流处理逻辑，fallback 指定熔断处理逻辑
     * 注意：
     * 1.blockHandler函数访问范围需要是public，且blockHandler函数默认需要和原方法在同一个类中。
     * 2.参数类型需要和原方法相匹配并且最后加一个额外的参数，类型为BlockException。
     * 若希望使用其他类的函数，则可以指定 blockHandlerClass为对应的类的Class对象，注意对应的函数必须为 static 函数，否则无法解析。
     */
    @Override
    @SentinelResource(value = "block",blockHandler = "handleBlockException",fallback = "blockFallback")
    public String block(String value){
        return "call block successfully : "+value+"~~";
    }

    /***
     * 限流操作处理，注意：最后要有一个BlockException类型参数
     */
    public String handleBlockException(String value, BlockException ex){
        ex.printStackTrace();
        return "handleBlock : 接口访问被限流了..."+value+"😭";
    }

    /***
     * 降级操作处理,Fallback 函数，函数签名与原函数一致或加一个 Throwable 类型的参数.
     */
    public String  blockFallback(String value){
        return "blockFallback :接口服务被熔断降级了... "+value+" o(*^▽^*)┛";
    }

    /***
     *
     * 使用 blockHandlerClass 指定限流业务处理类。
     * 使用 blockHandler 指定 blockHandlerClass中相应的 限流处理方法
     * 注意：blockHandlerClass 中对应的处理方法必须是 public static 的，且参数返回值与原方法一致，且最后添加一个额外的BlockException类型参数
     */

    /***
     * Sentinel 降级规则DEMO: 异常比例
     * 配置：
     * 降级策略: 异常比例
     * 异常比例: 0.2（即：20%）。当资源QPS>=5时，每秒异常数量/总通过数量的阈值,[0.1~1.0]表示[0%~100%]
     * 时间窗口: 1 (秒)。熔断开启后API无法访问的时间间隔
     */
    @Override
    @SentinelResource(value = "exceptionRatio",fallback = "exceptionRatioFallBack")
    public String exceptionRatio() throws RuntimeException {
        Random random = new Random();
        int i = random.ints(-100,10).findFirst().getAsInt();
        if(i<0){
            throw new RuntimeException("exceptionRatio调用异常：数据异常！"+i);
        }
        return "exceptionRatio调用成功："+i;
    }
    public String exceptionRatioFallBack(Throwable throwable){
        return "exceptionRatio FallBackHandler！"+ throwable.getMessage();
    }

    /***
     * Sentinel 降级规则DEMO: RT (平均响应时间)
     * 配置：
     * 降级策略: RT
     * RT 阈值: 200 (毫秒)
     * 时间窗口: 1 (秒)
     */
    @Override
    @SentinelResource(value = "rt", fallback = "rtFallBackHandler")
    public String rt() {
        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "RT 访问成功！"+ UUID.randomUUID().toString();
    }

    /***
     * RT熔断降级兜底方法
     */
    public String rtFallBackHandler(){
        return "RT FallBackHandler！"+ UUID.randomUUID().toString();
    }
}
